/**
 * @author Fang Lu, fanglupku@gmail.com
 * 2011-5-14
 */
package com.autotag.nlp;

import java.util.ArrayList;
import java.util.StringTokenizer;

public class AnalyzeResultOfTagging {
	private String originString;
	private String taggedString;
	private ArrayList<NLPToken> subjectTokenList = new ArrayList<NLPToken>();
	private ArrayList<NLPToken> actionTokenList = new ArrayList<NLPToken>();
	private ArrayList<NLPToken> objectTokenList = new ArrayList<NLPToken>();
	private ArrayList<NLPToken> otherTokenList = new ArrayList<NLPToken>();
	private ArrayList<NLPToken> allTokenList = new ArrayList<NLPToken>();
	private static PartOfSpeechTagger tagger = new PartOfSpeechTagger();
	public static String taggerString(String src){
		synchronized (tagger) {
			return tagger.tagString(src);
		}
	}
	public static void parseTaggedString(String taggedString,  ArrayList<NLPToken> subjectList,
			ArrayList<NLPToken> actionList, ArrayList<NLPToken> objectList, 
			ArrayList<NLPToken> otherList){
		StringTokenizer st = new StringTokenizer(taggedString);
		
		int index = 0;
		boolean hasSubject = false;
		boolean hasVerb = false;
		boolean hasObject = false;
		while (st.hasMoreTokens()){
			String thisStr = st.nextToken();
			NLPToken thisToken = new NLPToken(thisStr, index);
			if (thisToken.getType() == NLPToken.TYPE_N){
				if (hasSubject == false){
					subjectList.add(thisToken);
					++ index;
					while (st.hasMoreTokens()){
						thisStr = st.nextToken();
						thisToken = new NLPToken(thisStr, index);
						if (thisToken.getType() == NLPToken.TYPE_N){
							subjectList.add(thisToken);
						}else if (thisToken.getType() == NLPToken.TYPE_V){
							hasSubject = true;
							hasVerb = true;
							actionList.add(thisToken);
							++ index;
							break;
						}else {
							hasSubject = true;
							otherList.add(thisToken);
							++ index;
							break;
						}
						++index;
					}
				}else if (hasVerb == false){
					otherList.add(thisToken);
				}else if (hasObject == false){
					objectList.add(thisToken);
					++index;
					while (st.hasMoreTokens()){
						thisStr = st.nextToken();
						thisToken = new NLPToken(thisStr, index);
						if (thisToken.getType() == NLPToken.TYPE_N){
							objectList.add(thisToken);
						}else {
							hasObject = true;
							otherList.add(thisToken);
							++ index;
							break;
						}
						++index;
					}
				}else {
					otherList.add(thisToken);
				}
			}else if (thisToken.getType() == NLPToken.TYPE_V){
				if (hasVerb == false){
					hasVerb = true;
					actionList.add(thisToken);
				}else {
					otherList.add(thisToken);
				}
				hasSubject = true;
			}else{
				otherList.add(thisToken);
			}
			++ index;
		}
		
	}
	public void generateAllTokenList(){
		int index_subject = 0;
		int index_action = 0;
		int index_object = 0;
		int index_other = 0;
		while (true){
			if (index_subject >= subjectTokenList.size() 
					&& index_action >= actionTokenList.size() 
					&& index_object >= objectTokenList.size()
					&& index_other >= otherTokenList.size()){
				break;
			}
			int this_subject = Integer.MAX_VALUE;
			int this_action = Integer.MAX_VALUE;
			int this_object = Integer.MAX_VALUE;
			int this_other = Integer.MAX_VALUE;
			if (index_subject < subjectTokenList.size()){
				this_subject = subjectTokenList.get(index_subject).getIndex();
			}
			if (index_action < actionTokenList.size()){
				this_action = actionTokenList.get(index_action).getIndex();
			}
			if (index_object < objectTokenList.size()){
				this_object = objectTokenList.get(index_object).getIndex();
			}
			if (index_other < otherTokenList.size()){
				this_other = otherTokenList.get(index_other).getIndex();
			}
			int minIndex1 = Math.min(this_subject, this_action);
			int minIndex2 = Math.min(this_object, this_other);
			int min = Math.min(minIndex1, minIndex2);
			if (this_subject == min){
				allTokenList.add(subjectTokenList.get(index_subject));
				++ index_subject;
			}else if (this_action == min){
				allTokenList.add(actionTokenList.get(index_action));
				++ index_action;
			}else if (this_object == min){
				allTokenList.add(objectTokenList.get(index_object));
				++ index_object;
			}else if (this_other == min){
				allTokenList.add(otherTokenList.get(index_other));
				++ index_other;
			}
		}
	}
	public AnalyzeResultOfTagging(String originString){
		this.originString = originString;
		this.taggedString = taggerString(this.originString);
		parseTaggedString(taggedString, subjectTokenList, actionTokenList, objectTokenList, 
				otherTokenList);
		generateAllTokenList();
	}
	public String getOriginString() {
		return originString;
	}
	public String getTaggedString() {
		return taggedString;
	}
	public ArrayList<NLPToken> getObjectTokenList() {
		return objectTokenList;
	}
	public ArrayList<NLPToken> getActionTokenList() {
		return actionTokenList;
	}
	public ArrayList<NLPToken> getSubjectTokenList() {
		return subjectTokenList;
	}
	public ArrayList<NLPToken> getOtherTokenList() {
		return otherTokenList;
	}
	public ArrayList<NLPToken> getAllTokenList() {
		return allTokenList;
	}
	public String toString(){
		StringBuffer sb = new StringBuffer();
		
		sb.append("originString:");
		sb.append(originString);
		sb.append("\n");
		sb.append("taggedString:");
		sb.append(taggedString);
		sb.append("\n");
		sb.append("subject list:{");
		for (int i=0; i<subjectTokenList.size(); ++i){
			if (i > 0){
				sb.append("/");
			}
			sb.append(subjectTokenList.get(i).getContent());
		}
		sb.append("}\n");
		sb.append("action list:{");
		for (int i=0; i<actionTokenList.size(); ++i){
			if (i > 0){
				sb.append("/");
			}
			sb.append(actionTokenList.get(i).getContent());
		}
		sb.append("}\n");
		sb.append("object list:{");
		for (int i=0; i<objectTokenList.size(); ++i){
			if (i > 0){
				sb.append("/");
			}
			sb.append(objectTokenList.get(i).getContent());
		}
		sb.append("}\n");
		sb.append("other list:{");
		for (int i=0; i<otherTokenList.size(); ++i){
			if (i > 0){
				sb.append("/");
			}
			sb.append(otherTokenList.get(i).getContent());
		}
		sb.append("}\n");
		
		
		return sb.toString();
	}
	public ArrayList<String> getStemmedNounPhraseList(){
		ArrayList<String> resultList = new ArrayList<String>();
		
		for (int i=0; i<allTokenList.size(); ++i){
			NLPToken thisToken = allTokenList.get(i);
			if (thisToken.getType() == NLPToken.TYPE_N){
				String thisWordStem = WordStemmer.getStem(thisToken.getContent().toLowerCase());
				StringBuffer sb = new StringBuffer();
				sb.append(thisWordStem);
				int count = 0;
				for (int j=i+1; j<allTokenList.size(); ++j){
					thisToken = allTokenList.get(j);
					if (thisToken.getType() != NLPToken.TYPE_N){
						break;
					}
					thisWordStem = WordStemmer.getStem(thisToken.getContent().toLowerCase());
					sb.append(" ");
					sb.append(thisWordStem);
					++count;
				}
				i += count;
				resultList.add(sb.toString());
			}
		}
		
		return resultList;
	}
	public static void main(String []args){
		AnalyzeResultOfTagging result = new AnalyzeResultOfTagging("Pay Pal API Interface Service");
		System.out.println(result);
		ArrayList<String> nounList = result.getStemmedNounPhraseList();
		for (String string : nounList) {
			System.out.println(string);
		}
	}
}
